package continuum.db.dao;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;

import continuum.db.dao.util.QueryParameter;
import continuum.db.exceptions.DaoException;

/**
 * This is the basic class providing the implementation of the continuum DAOs.
 * It implements methods in the {@link Dao} interface that are shared across
 * each DAO implementation (unless a particular DAO needs to override it).
 * 
 * @author bdgould
 * 
 * @param <T>
 * @param <PK>
 */
public abstract class DaoImpl<T, PK extends Serializable> implements Dao<T, PK> {

	protected final Logger log = Logger.getLogger(getClass());

	protected Class<T> type;

	@Resource
	protected SessionFactory sessionFactory;

	protected DaoImpl(Class<T> type) {
		this.type = type;
		log.info("Constructed DAO for type " + type.getName());
	}

	@Override
	@SuppressWarnings("unchecked")
	public PK insert(T newEntity) throws DaoException {
		return (PK) sessionFactory.getCurrentSession().save(newEntity);

	}

	@Override
	public void update(T transientObject) throws DaoException {
		sessionFactory.getCurrentSession().update(transientObject);
	}

	@Override
	public void upsert(T transientObject) throws DaoException {
		sessionFactory.getCurrentSession().saveOrUpdate(transientObject);
	}

	@Override
	public void delete(T persistentObject) throws DaoException {
		sessionFactory.getCurrentSession().delete(persistentObject);
	}

	@Override
	@SuppressWarnings("unchecked")
	public T select(PK id) throws DaoException {
		return (T) sessionFactory.getCurrentSession().get(type, id);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> selectAll() throws DaoException {
		Criteria criteria = getSession().createCriteria(type);
		return criteria.add(Restrictions.naturalId()).list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> selectAllByField(QueryParameter... parameters)
			throws DaoException {
		Criteria criteria = getSession().createCriteria(type);
		for (QueryParameter param : parameters) {
			criteria.add(Restrictions.eq(param.getFieldName(), param.getValue()));
		}
		return criteria.list();
	}

	/**
	 * 
	 * @return The current {@link Session} object
	 */
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

}
